// let fn = function(){
//     console.log('hello First-class Function')
// }
// fn()
// 高阶函数作为参数
// forEach
// function forEach ( array, fn){
//     for(let i = 0 ;i < array.length;i++){
//         fn(array[i])
//     }
// }
//测试
// let arr = [1,3,5,7,9]
// forEach(arr,function(item){
//     console.log(item)
// })
// function filter(array,fn){
//     let results = []
//     for(let i = 0 ;i < array.length;i++){
//        if(fn(array[i])) {
//            results.push(array[i])
//        }
//     }
//     return results
// }
// //测试
// let arr = [1,3,5,8,9]
// let r = filter(arr,function(item){
//     return item % 2 ===0
// })

// console.log(r)
// 总结
// 函数作为参数的好处，更灵活，不考虑怎么实现

// <------------>

// 函数作为返回值
// function makeFn(){
//     let msg = 'hello function'
//     return function(){
//         console.log(msg)
//     }
// }
// const fn = makeFn()
// fn()
// makeFn()()

//once（只被执行一次） 场景：支付
// 函数  重复利用
//  function once (fn){
//      let done = false
//      return function (){
//          if(!done){
//              done = true
//              console.log(this,arguments)
//            return   fn.apply(this,arguments)
//          }
//      } 
//  }
//  测试
// let pay = once(function(money){
//     console.log(`支付了${money}RMB`)
// })
// pay(5)
// pay(6)
// pay(7)
// <------------------->
// 高级函数的意义
// 1，抽象可以帮我们屏蔽细节，只需要关注与我们的目标
// 2，高阶函数是用来抽象通用的问题

//面向过程的方式
// let array =[1,2,3,4]
// for(let i =0 ;i<array.length;i++){
//     console.log(array[i])
// }
// console.log('-------')
// 高阶函数
// function forEach ( array, fn){
//     for(let i = 0 ;i < array.length;i++){
//         fn(array[i])
//     }
// }
// forEach(array,item =>{
//     console.log(item)
// } )
// 灵活，代码简洁

// 常用高阶函数
// forEach map filter every some find/findIndex reduce sort

// 模拟常用高阶函数：map ,every ,some
//map
// const map =(array,fn) =>{
//  let results = []
//  for (let value of array){
//      results.push(fn(value))
//  }
//  return results
// }
// 测试
// let arr = [1,2,3,4,5]
// arr = map (arr,v =>v *v)
// console.log(arr)

//every 
// const every = (array,fn) =>{
//     let result =true
//     for(let value of array){
//         result = fn(value)
//         if(!result){
//             break
//         }
//     }
//     return result
// }
// 测试
// let arr =[12,24]
// let r = every(arr ,v=>v>10)
// console.log(r)
//some 
// const some = (array,fn) =>{
//     let result =false
//     for(let value of array){
//         result= fn(value)
//         if(result){
//          break
//         }
//     }
//     return result
// }
// let arr = [1,21,41,59,9]
// let r = some(arr,v => v%2 ===0)
// console.log(r)

// 闭包
//  函数和其周围的状态（词法环境）的引用捆绑在一起形成闭包 
//  可以在另一作用域中调用一个函数并访问到该函数的作用域中的成员 
// function makeFn(){
//     let msg = 'hello function'
//     return function(){
//         console.log(msg)
//     }
// }
// const fn = makeFn()
// fn()

//once（只被执行一次） 场景：支付
// 函数  重复利用
//  function once (fn){
//      let done = false
//      return function (){
//          if(!done){
//              done = true
//              console.log(this,arguments)
//            return   fn.apply(this,arguments)
//          }
//      } 
//  }
//  测试
// let pay = once(function(money){
//     console.log(`支付了${money}RMB`)
// })
// pay(5)
// pay(6)
// pay(7)


// 闭包的本质：
// 函数在执行的时候会放到一个执行栈上当函数执行完毕之后会从执行栈上移除，但是
// 堆上的作用域成员因为被外部引用不能释放，因此内部函数依然可以访问外部函数的成员
